package com.acmen.ump.core.jwt;

import com.acmen.ump.entity.sys.SysUser;
import org.jose4j.jwk.RsaJsonWebKey;
import org.jose4j.jwk.RsaJwkGenerator;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;

import java.util.Random;

public class JwtUtil {
    /**
     * RsaJsonWebKeyBuilder 采用单例模式获取rsaJsonWebKey, 这样任何时候都可以得到同样的公钥/私钥对
     */
    private static class RsaJsonWebKeyBuilder {
        private static volatile RsaJsonWebKey rsaJsonWebKey;
        private RsaJsonWebKeyBuilder(){}
        public static RsaJsonWebKey getRasJsonWebKeyInstance() {
            if(rsaJsonWebKey == null) {
                synchronized (RsaJsonWebKey.class) {
                    if(rsaJsonWebKey == null){
                        try {
                            rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
                            rsaJsonWebKey.setKeyId(String.valueOf(new Random().nextLong()));
                        } catch(Exception e){
                            return null;
                        }
                    }
                }
            }
            return rsaJsonWebKey;
        }
    }

    public static String generateToken(SysUser user, int expiration) throws Exception{
        JwtClaims jwtClaims = new JwtClaims();
        jwtClaims.setIssuer("email");
        jwtClaims.setAudience(System.getProperty("ump"));
        jwtClaims.setExpirationTimeMinutesInTheFuture(expiration);
        jwtClaims.setGeneratedJwtId();
        jwtClaims.setIssuedAtToNow();
        jwtClaims.setNotBeforeMinutesInThePast(2);
        jwtClaims.setSubject("Bearer");

        JsonWebSignature jsonWebSignature = new JsonWebSignature();
        jsonWebSignature.setPayload(jwtClaims.toJson());
        jsonWebSignature.setKey(RsaJsonWebKeyBuilder.getRasJsonWebKeyInstance().getPrivateKey());
        jsonWebSignature.setKeyIdHeaderValue(RsaJsonWebKeyBuilder.getRasJsonWebKeyInstance().getKeyId());
        jsonWebSignature.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);

        String jwt = jsonWebSignature.getCompactSerialization();

        return "Bearer " + jwt;
    }

    public static boolean verifyToken(String token, String account) {  // 由于生成token时使用了用户的email作为issuer，故这里需要传入email来做校验，这样做可以防止对不同用户的修改操作
        String tokenContent = token.substring(7);
        JwtConsumer consumer = new JwtConsumerBuilder()
                .setRequireExpirationTime()
                .setMaxFutureValidityInMinutes(5256000)
                .setAllowedClockSkewInSeconds(30)
                .setRequireSubject()
                .setExpectedIssuer(account)
                .setExpectedSubject("Bearer")
                .setExpectedAudience(System.getProperty("ump"))
                .setVerificationKey(RsaJsonWebKeyBuilder.getRasJsonWebKeyInstance().getPublicKey())
                .build();
        try {
            JwtClaims claims = consumer.processToClaims(tokenContent);
            return true;
        } catch (InvalidJwtException e) {
            return false;
        }
    }
}